home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Source Code
/
Visual Basic Source Code.iso
/
vbsource
/
vbdatabs
/
strdbt.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-28
|
89KB
|
3,242 lines
// ------------------------------- //
// -------- Start of File -------- //
// ------------------------------- //
// ----------------------------------------------------------- //
// C++ Source Code File Name: strdbt.cpp
// Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
// Produced By: Doug Gaer
// File Creation Date: 09/18/1997
// Date Last Modified: 03/29/1999
// Copyright (c) 1997 Douglas M. Gaer
// ----------------------------------------------------------- //
// ------------- Program Description and Details ------------- //
// ----------------------------------------------------------- //
/*
The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
All those who put this code or its derivatives in a commercial
product MUST mention this copyright in their documentation for
users of the products in which this code or its derivative
classes are used. Otherwise, you have the freedom to redistribute
verbatim copies of this source code, adapt it to your specific
needs, or improve the code and release your improvements to the
public provided that the modified files carry prominent notices
stating that you changed the files and the date of any change.
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
CORRECTION.
The string database is a general-purpose object-oriented
database. This version is designed to work with a terminal
interface.
- Modify "dbconfig.h" file to customize the database
- Modify "dbvers.h" file to uniquely identify the database
- Modify "dbtcfg.h" file to customize this program
- Modify "version.h" file to report changes and fixes
*/
// ----------------------------------------------------------- //
#include <fstream.h> // Using ofstream to print to a text file
#include "strdb_sh.h"
#include "terminal.h"
#include "config.h"
#include "timer.h"
#include "strutil.h"
#include "asprint.h"
#include "pscript.h"
#include "vbdstats.h"
#include "btwalker.h"
#include "htmldrv.h"
// Application specific include files
#include "version.h"
#include "dbconfig.h"
#include "dbtcfg.h"
static POD *DB; // Global database pointer
const int KeyBuf = 25; // Users input limit per string
const int CBuf = 81; // Input limit for comments
const int StringOffset = 15; // Display output limit per string
const int IntOffset = 8; // Display output limit per number
const char *WildCard = "*"; // Used for wild card searches
const int retrys = 3; // Times to retry user input operations
// Define configurable parameters
int CacheSize = 15; // Memory cache size for the index file
int AdminRights = 0; // Define user privileges
// Define file access modes used in the application
VBDFile::AccessMode RWMode = VBDFile::READWRITE;
VBDFile::AccessMode ROMode = VBDFile::READONLY;
// Menu menu setup
typedef void (*MMF) (); // Pointer to (M)ain (M)enu (F)unctions
const int MMSelections = 6; // Main menu selections
// Main menu functions
void Exit();
void ISRMenu(); // Insertion/Removal menu
void FindMenu(); // Query menu
void DisplayMenu(); // Display menu
void FileMenu(); // File operations menu
void PrintMenu(); // Print menu
const char *mainmenu[MMSelections] = {
"(0) - Exit this program",
"(1) - Add, Remove, or Change items in the database",
"(2) - Find items in the database",
"(3) - Display items in the database",
"(4) - File Operations",
"(5) - Print Menu"
};
MMF MMFunctions[MMSelections] = {
&Exit,
&ISRMenu,
&FindMenu,
&DisplayMenu,
&FileMenu,
&PrintMenu
};
// Insertion/Removal menu setup
typedef void (*ISRMF) (); // Pointer to (A)dd (M)enu (F)unctions
const char *ISRMTitle = "--------- DATABASE INSERTION/REMOVAL MENU ---------";
const int ISRMSelections = 4; // Insertion/Removal menu selections
// Insertion/Removal menu functions
void Return();
void Add();
void Change();
void Remove();
const char *isrmenu[ISRMSelections] = {
"(0) - Return to main menu",
"(1) - Add items to the database",
"(2) - Change an item in the database",
"(3) - Remove an item from the database"
};
ISRMF ISRMFunctions[ISRMSelections] = {
&Return,
&Add,
&Change,
&Remove
};
// Find menu setup
typedef void (*FMF) (); // Pointer to (F)ind (M)enu (F)unctions
const char *FMTitle = "---------- DATABASE QUERY MENU ----------";
const int FMSelections = 10; // Find menu selections
// Find menu functions
void Return();
void FindByKeyName();
void FindByM2Name();
void FindByM3Name();
void FindByM4Name();
void FindByM5Name();
void FindByM6Name();
void FindByM7Name();
void FindByM8Name();
void FindByComments();
FMF FMFunctions[FMSelections] = {
&Return,
&FindByKeyName,
&FindByM2Name,
&FindByM3Name,
&FindByM4Name,
&FindByM5Name,
&FindByM6Name,
&FindByM7Name,
&FindByM8Name,
&FindByComments
};
// Display menu setup
typedef void (*DMF) (); // Pointer to (D)isplay (M)enu (F)unctions
const char *DMTitle = "---------- DATABASE DISPLAY MENU ----------";
const int DMSelections = 3; // Display menu selections
// Display menu functions
void DisplayLBL(); // Display all objects line by line
void DisplayAll(); // Display all objects one at a time
const char *displaymenu[DMSelections] = {
"(0) - Return to main menu",
"(1) - Display all items line by line",
"(2) - Display all items one a time"
};
DMF DMFunctions[DMSelections] = {
&Return,
&DisplayLBL,
&DisplayAll
};
// File operations menu setup
typedef void (*FOMF) (); // Pointer to (F)ile (M)enu (F)unctions
const char *FOMTitle = "---------- DATABASE FILE OPERATIONS MENU ----------";
const int FOMSelections = 9; // File operations menu selections
// File operations menu functions
void FileStats();
void ExportToASCII();
void ImportFromASCII();
void BackUp();
void Merge();
void CreateTemplate();
void CompareIndexFile();
void RebuildIndexFile();
const char *filemenu[FOMSelections] = {
"(0) - Return to main menu",
"(1) - Display Variable Block Database statistics",
"(2) - Export to ASCII file (delimited by tabs)",
"(3) - Import ASCII file (delimited by tabs)",
"(4) - Backup the database to another file",
"(5) - Merge the contents of another database file",
"(6) - Create a template for an import file",
"(7) - Compare the index file to the data file",
"(8) - Rebuild the index file"
};
FOMF FOMFunctions[FOMSelections] = {
&Return,
&FileStats,
&ExportToASCII,
&ImportFromASCII,
&BackUp,
&Merge,
&CreateTemplate,
&CompareIndexFile,
&RebuildIndexFile
};
// Print menu setup
typedef void (*PMF) (); // Pointer to (P)rint (M)enu (F)unctions
const char *PMTitle = "---------- DATABASE PRINTING MENU ----------";
const int PMSelections = 6; // Print menu selections
// Print menu functions
void ASCIIPrintAll(); // Print database to an ASCII file (abbreviated)
void ASCIIPrintAllLong(); // Print database to an ASCII file (full listing)
void ASCIIPrintObject(); // Print a single object to an ASCII file
void PostScriptPrint(); // Print database to a PostScript file
void HTMLPrint(); // Print the database to an html file
const char *printmenu[PMSelections] = {
"(0) - Return to main menu",
"(1) - Print to text file (abbreviated, 80 cols)",
"(2) - Print to text file (full listing, 132 cols)",
"(3) - Print a single object to a text file",
"(4) - Print to PostScript file",
"(5) - Print to an HTML file"
};
PMF PMFunctions[PMSelections] = {
&Return,
&ASCIIPrintAll,
&ASCIIPrintAllLong,
&ASCIIPrintObject,
&PostScriptPrint,
&HTMLPrint
};
// Function prototypes for functions use by all menu functions
void AddObject(StrDB &strdb, Coords *p);
void ChangeObject(StrDB &strdb, Coords *p, int adding = 0);
void DisplayObject(StrDB &strdb, Coords *p);
void LineByLine(StrDB &strdb, Coords *p);
void DisplayString(const char *s);
int LoadIndexKeys();
// Search functions
void FindBy(const char *MemberName, StrDBItem item);
void StrDBSearch(StrDB &strdb, StrDBItem item, UString &str,
Coords *p, const char *wildcard = 0);
enum PrintMode {
PORTRAIT,
LANDSCAPE
};
void PrintItemBar(ofstream &stream, int abv = 1);
void PrintLineByLine(StrDB &strdb, ofstream &stream, int abv = 1);
int ASCIIPrint(PrintMode mode);
void PrintObject(StrDB &strdb, Coords *p);
int PrintPSItemBar(ofstream &stream, PostScriptDrv &psdrv,
int x_offset, int char_offset, int max_len);
void MainMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(MMTitle));
p->SetY(terminal->ScreenCenter(MMSelections));
terminal->ClearScreen();
terminal->Write(MMTitle, p->XPos(), p->YPrev());
for(int i = 0; i < MMSelections; i++)
terminal->Write(mainmenu[i], p->XPos(), p->YOffset(1));
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*MMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*MMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*MMFunctions[2]) (); // Call the appropriate menu function
break;
case '3':
(*MMFunctions[3]) (); // Call the appropriate menu function
break;
case '4':
(*MMFunctions[4]) (); // Call the appropriate menu function
break;
case '5':
(*MMFunctions[5]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void ISRMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(ISRMTitle));
p->SetY(terminal->ScreenCenter(ISRMSelections));
terminal->ClearScreen();
terminal->Write(ISRMTitle, p->XPos(), p->YPrev());
for(int i = 0; i < ISRMSelections; i++)
terminal->Write(isrmenu[i], p->XPos(), p->YOffset(1));
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*ISRMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*ISRMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*ISRMFunctions[2]) (); // Call the appropriate menu function
break;
case '3':
(*ISRMFunctions[3]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void FindMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(FMTitle));
p->SetY(terminal->ScreenCenter(FMSelections));
terminal->ClearScreen();
terminal->Write(FMTitle, p->XPos(), p->YPrev());
terminal->Write("(0) - Return to main menu", p->XPos(), p->YOffset(1));
if(KeyName != 0) {
terminal->Write("(1) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(KeyName);
}
if(M2Name != 0) {
terminal->Write("(2) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M2Name);
}
if(M3Name != 0) {
terminal->Write("(3) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M3Name);
}
if(M4Name != 0) {
terminal->Write("(4) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M4Name);
}
if(M5Name != 0) {
terminal->Write("(5) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M5Name);
}
if(M6Name != 0) {
terminal->Write("(6) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M6Name);
}
if(M7Name != 0) {
terminal->Write("(7) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M7Name);
}
if(M8Name != 0) {
terminal->Write("(8) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(M8Name);
}
if(Comments != 0) {
terminal->Write("(9) - Find by ", p->XPos(), p->YOffset(1));
terminal->Write(Comments);
}
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*FMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*FMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*FMFunctions[2]) (); // Call the appropriate menu function
break;
case '3':
(*FMFunctions[3]) (); // Call the appropriate menu function
break;
case '4':
(*FMFunctions[4]) (); // Call the appropriate menu function
break;
case '5':
(*FMFunctions[5]) (); // Call the appropriate menu function
break;
case '6':
(*FMFunctions[6]) (); // Call the appropriate menu function
break;
case '7':
(*FMFunctions[7]) (); // Call the appropriate menu function
break;
case '8':
(*FMFunctions[8]) (); // Call the appropriate menu function
break;
case '9':
(*FMFunctions[9]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void DisplayMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(DMTitle));
p->SetY(terminal->ScreenCenter(DMSelections));
terminal->ClearScreen();
terminal->Write(DMTitle, p->XPos(), p->YPrev());
for(int i = 0; i < DMSelections; i++)
terminal->Write(displaymenu[i], p->XPos(), p->YOffset(1));
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*DMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*DMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*DMFunctions[2]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void FileMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(FOMTitle));
p->SetY(terminal->ScreenCenter(FOMSelections));
terminal->ClearScreen();
terminal->Write(FOMTitle, p->XPos(), p->YPrev());
for(int i = 0; i < FOMSelections; i++)
terminal->Write(filemenu[i], p->XPos(), p->YOffset(1));
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*FOMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*FOMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*FOMFunctions[2]) (); // Call the appropriate menu function
break;
case '3':
(*FOMFunctions[3]) (); // Call the appropriate menu function
break;
case '4':
(*FOMFunctions[4]) (); // Call the appropriate menu function
break;
case '5':
(*FOMFunctions[5]) (); // Call the appropriate menu function
break;
case '6':
(*FOMFunctions[6]) (); // Call the appropriate menu function
break;
case '7':
(*FOMFunctions[7]) (); // Call the appropriate menu function
break;
case '8':
(*FOMFunctions[8]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void PrintMenu()
{
int c;
Coords *p = new Coords(0, 0);
while(1) {
p->SetXY(0, 0);
p->SetX(terminal->Center(PMTitle));
p->SetY(terminal->ScreenCenter(PMSelections));
terminal->ClearScreen();
terminal->Write(PMTitle, p->XPos(), p->YPrev());
for(int i = 0; i < PMSelections; i++)
terminal->Write(printmenu[i], p->XPos(), p->YOffset(1));
terminal->Write("Press the number of your selection -> ",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case '0':
(*PMFunctions[0]) (); // Call the appropriate menu function
return;
case '1':
(*PMFunctions[1]) (); // Call the appropriate menu function
break;
case '2':
(*PMFunctions[2]) (); // Call the appropriate menu function
break;
case '3':
(*PMFunctions[3]) (); // Call the appropriate menu function
break;
case '4':
(*PMFunctions[4]) (); // Call the appropriate menu function
break;
case '5':
(*PMFunctions[5]) (); // Call the appropriate menu function
break;
default:
break;
}
}
}
void Exit()
{
// Nothing to do
}
void Return()
{
// Nothing to do
}
int LoadIndexKeys()
{
// Clear the doubly linked list
dllist->Clear();
BtreeWalker btw(DB->Index());
unsigned num_objects = btw.Sort(LoadKeys);
return num_objects;
}
void DisplayAll()
{
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.", 0, 1);
terminal->AnyKey(0, 2);
return;
}
StrDB strdb(DB);
Coords *p = new Coords(0, 0);
terminal->ClearScreen();
LoadIndexKeys();
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
terminal->ClearScreen();
p->SetXY(0, 0); // Reset x and y positions
strdb.ReadObject(dllistptr->Data.object_address);
DisplayObject(strdb, p);
terminal->Write("(C)-Change, (D)-Delete, (P)-Print, (X)-Exit",
p->XPos(), p->YOffset(2));
terminal->Write(", Any other key to continue");
int c = terminal->GetChar();
switch(c) {
case 'c': case 'C':
terminal->ClearScreen();
p->SetXY(0, 0);
ChangeObject(strdb, p);
break;
case 'd': case 'D': {
int yn = terminal->YesNo("Are you sure you want to delete (y/n)",
p->XPos(), p->YOffset(2));
if(!yn) break;
strdb.DeleteObject();
break;
}
case 'p': case 'P':
p->YOffset(1);
PrintObject(strdb, p);
break;
case 'x': case 'X':
dllist->Clear();
delete p;
return;
default:
break;
}
dllistptr = dllistptr->GetNext();
}
dllist->Clear();
delete p;
}
void ItemBar(Coords *p)
// Displays the Key data member and the data member 2 - 5
{
int x = p->XPos();
if(KeyName != 0) terminal->Write(KeyName, p->XPos(), p->YPos());
if(M2Name != 0)
terminal->Write(M2Name, p->XOffset(StringOffset+1), p->YPos());
if(M3Name != 0)
terminal->Write(M3Name, p->XOffset(StringOffset+1), p->YPos());
if(M4Name != 0)
terminal->Write(M4Name, p->XOffset(StringOffset+1), p->YPos());
if(M5Name != 0)
terminal->Write(M5Name, p->XOffset(StringOffset+1), p->YPos());
terminal->MoveCursor(0, p->YOffset(1));
int i = 0;
while (i++ < terminal->MaxCols()-1) terminal->Write('=');
p->YOffset(1);
p->SetX(x);
}
void DisplayLBL()
{
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.", 0, 1);
terminal->AnyKey(0, 2);
return;
}
StrDB strdb(DB);
int c;
unsigned count = 0;
Coords *p = new Coords(0, 0);
terminal->ClearScreen();
ItemBar(p);
LoadIndexKeys();
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
// Display the first object
strdb.ReadObject(dllistptr->Data.object_address);
LineByLine(strdb, p);
p->YOffset(1);
dllistptr = dllistptr->GetNext();
count++;
if(count > 5) {
terminal->Write("(X)-Exit", p->XPos(), p->YOffset(2));
terminal->Write(", Any other key to continue");
c = terminal->GetChar();
switch(c) {
case 'x': case 'X':
dllist->Clear();
delete p; // Free Coords pointer
return;
default:
break;
}
terminal->ClearScreen();
p->SetXY(0, 0);
ItemBar(p);
count = 0;
}
}
terminal->AnyKey(p->XPos(), p->YOffset(2));
dllist->Clear();
delete p; // Free Coords pointer
}
void Remove()
{
if(KeyName == 0) return;
if(!AdminRights) {
terminal->ClearScreen();
terminal->Write("You do not have Admin User Privileges", 0, 1);
terminal->AnyKey(0, 2);
return;
}
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
char buf[KeyBuf];
terminal->Write(KeyName, p->XPos(), p->YPos());
terminal->Write(" to delete -> ");
terminal->GetString(buf);
StrDB strdb(DB);
strdb.SetKM(buf);
FAU addr = strdb.FindObject();
if(!addr) {
terminal->Write("Could not find: ", p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coord pointer
return;
}
int yn = terminal->YesNo("Are you sure you want to delete (y/n)",
p->XPos(), p->YOffset(2));
if(!yn) {
delete p; // Free Coord pointer
return;
}
strdb.DeleteObject();
terminal->Write("Deleted entry for: ", p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free Coord pointer
}
void FileStats()
{
VBDStats(terminal, DB->OpenDatabase());
VBDStats(terminal, DB->OpenIndexFile());
}
void PrintItemBar(ofstream &stream, int abv)
{
int i = 0;
if(KeyName != 0) ASPrint(KeyName, stream, StringOffset+1);
if(M2Name != 0) ASPrint(M2Name, stream, StringOffset+1);
if(M3Name != 0) ASPrint(M3Name, stream, StringOffset+1);
if(M4Name != 0) ASPrint(M4Name, stream, StringOffset+1);
if(abv) { // Print abbreviated list for portrait print outs
if(M5Name != 0) ASPrint(M5Name, stream, StringOffset);
stream << asLineFeed;
i = 0;
while (i++ < asPrintCols-1) stream << '=';
stream << asLineFeed;
return;
}
else { // Print full listing for landscape print outs
if(M5Name != 0) ASPrint(M5Name, stream, StringOffset+1);
if(M6Name != 0) ASPrint(M6Name, stream, StringOffset+1);
if(M7Name != 0) ASPrint(M7Name, stream, StringOffset+1);
if(M8Name != 0) ASPrint(M8Name, stream, StringOffset);
stream << asLineFeed;
i = 0;
while (i++ < asPrintColsLong-1) stream << '=';
stream << asLineFeed;
}
}
void PrintLineByLine(StrDB &strdb, ofstream &stream, int abv)
{
int i = 0;
if(KeyName != 0) ASPrint(strdb.GetKM(), stream, StringOffset+1);
if(M2Name != 0) ASPrint(strdb.GetM2(), stream, StringOffset+1);
if(M3Name != 0) ASPrint(strdb.GetM3(), stream, StringOffset+1);
if(M4Name != 0) ASPrint(strdb.GetM4(), stream, StringOffset+1);
if(abv) { // Print abbreviated list for portrait print outs
if(M5Name != 0) ASPrint(strdb.GetM5(), stream, StringOffset);
stream << asLineFeed;
i = 0;
while (i++ < asPrintCols-1) stream << '-';
stream << asLineFeed;
return;
}
else { // Print full listing for landscape print outs
if(M5Name != 0) ASPrint(strdb.GetM5(), stream, StringOffset+1);
if(M6Name != 0) ASPrint(strdb.GetM6(), stream, StringOffset+1);
if(M7Name != 0) ASPrint(strdb.GetM7(), stream, StringOffset+1);
if(M8Name != 0) ASPrint(strdb.GetM8(), stream, StringOffset);
stream << asLineFeed;
i = 0;
while (i++ < asPrintColsLong-1) stream << '-';
stream << asLineFeed;
}
}
void ASCIIPrintAll()
{
ASCIIPrint(PORTRAIT);
}
void ASCIIPrintAllLong()
{
ASCIIPrint(LANDSCAPE);
}
int ASCIIPrint(PrintMode mode)
{
char buf[CBuf];
char *FileName;
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
terminal->Write("Enter file name to print to: ",
p->XPos(), p->YPos());
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(2));
if(!yn) {
delete p;
delete[] tmp;
return 0;
}
}
FileName = tmp;
delete[] tmp;
ofstream stream(FileName, ios::out); // Open file and truncate it
terminal->Write("Printing to: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return 0;
}
terminal->Write("Printing...", p->XPos(), p->YOffset(2));
StrDB strdb(DB);
unsigned count = 0;
if(mode == LANDSCAPE)
PrintItemBar(stream, 0);
else
PrintItemBar(stream);
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
return 0;
}
LoadIndexKeys();
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
strdb.ReadObject(dllistptr->Data.object_address);
switch(mode) {
case PORTRAIT:
PrintLineByLine(strdb, stream);
break;
case LANDSCAPE:
PrintLineByLine(strdb, stream, 0);
break;
default:
delete p; // Free the Coords pointer
return 0;
}
count++;
dllistptr = dllistptr->GetNext();
}
dllist->Clear();
terminal->Write("Finished", p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
stream.close();
return count;
}
void ASCIIPrintObject()
{
if(KeyName == 0) return;
Coords *p = new Coords(0, 0);
char buf[KeyBuf];
terminal->ClearScreen();
terminal->Write(KeyName, p->XPos(), p->YPos());
terminal->Write(" to print -> ");
terminal->GetString(buf);
StrDB strdb(DB);
strdb.SetKM(buf);
FAU addr = strdb.FindObject();
if(!addr) {
terminal->Write("Could not find: ", p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free Coords pointer
return;
}
PrintObject(strdb, p);
delete p; // Free Coords pointer
}
void PrintObject(StrDB &strdb, Coords *p)
{
char buf[CBuf];
char *FileName;
const char *separator = " = ";
const char *cseparator = ": ";
terminal->Write("Enter file name to print to: ",
p->XPos(), p->YOffset(1));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(1));
terminal->Write(tmp);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(1));
if(!yn) {
delete[] tmp;
return;
}
}
FileName = tmp;
delete[] tmp;
ofstream stream(FileName, ios::out); // Open file and truncate it
terminal->Write("Printing to: ",
p->XPos(), p->YOffset(1));
terminal->Write(FileName);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(1));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
return;
}
if(KeyName != 0) {
ASPrint(KeyName, stream, strlen(KeyName));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetKM(), stream, strlen(strdb.GetKM()));
stream << asLineFeed;
}
if(M2Name != 0) {
ASPrint(M2Name, stream, strlen(M2Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM2(), stream, strlen(strdb.GetM2()));
stream << asLineFeed;
}
if(M3Name != 0) {
ASPrint(M3Name, stream, strlen(M3Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM3(), stream, strlen(strdb.GetM3()));
stream << asLineFeed;
}
if(M4Name != 0) {
ASPrint(M4Name, stream, strlen(M4Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM4(), stream, strlen(strdb.GetM4()));
stream << asLineFeed;
}
if(M5Name != 0) {
ASPrint(M5Name, stream, strlen(M5Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM5(), stream, strlen(strdb.GetM5()));
stream << asLineFeed;
}
if(M6Name != 0) {
ASPrint(M6Name, stream, strlen(M6Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM6(), stream, strlen(strdb.GetM6()));
stream << asLineFeed;
}
if(M7Name != 0) {
ASPrint(M7Name, stream, strlen(M7Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM7(), stream, strlen(strdb.GetM7()));
stream << asLineFeed;
}
if(M8Name != 0) {
ASPrint(M8Name, stream, strlen(M8Name));
ASPrint(separator, stream, strlen(separator));
ASPrint(strdb.GetM8(), stream, strlen(strdb.GetM8()));
stream << asLineFeed;
}
if(Comments != 0) {
ASPrint(Comments, stream, strlen(Comments));
ASPrint(cseparator, stream, strlen(cseparator));
ASPrint(strdb.GetCM(), stream, strlen(strdb.GetCM()));
stream << asLineFeed;
}
terminal->Write("Finished", p->XPos(), p->YOffset(1));
terminal->AnyKey(p->XPos(), p->YOffset(2));
stream.close();
}
void Add()
{
if(KeyName == 0) return;
if(!AdminRights) {
terminal->ClearScreen();
terminal->Write("You do not have Admin User Privileges", 0, 1);
terminal->AnyKey(0, 2);
return;
}
int r = retrys;
Coords *p = new Coords(0, 0);
char buf[KeyBuf];
terminal->ClearScreen();
while(1) {
terminal->Write(KeyName, p->XPos(), p->YPos());
terminal->Write(" to add -> ");
terminal->GetString(buf);
if(!*buf) r--; else break;
if(!r) {
delete p;
return;
}
}
StrDB strdb(DB);
UString key_buf(buf);
// Remove any leading space from the key name entry
int offset = key_buf.Find(" ");
if(offset == 0) key_buf.DeleteAt(offset, 1);
if(key_buf == "") { // Check for a key name valid input
delete p;
return;
}
strdb.SetKM(key_buf);
FAU addr = strdb.FindObject();
if(addr) {
terminal->Write(buf, p->XPos(), p->YOffset(2));
terminal->Write(" entry already exists.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free Coords pointer
return;
}
AddObject(strdb, p);
delete p; // Free Coords pointer
}
void AddObject(StrDB &strdb, Coords *p)
{
char buf[KeyBuf];
char cbuf[CBuf];
if(M2Name != 0) {
terminal->Write(M2Name, p->XPos(), p->YOffset(2));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM2(buf);
}
if(M3Name != 0) {
terminal->Write(M3Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM3(buf);
}
if(M4Name != 0) {
terminal->Write(M4Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM4(buf);
}
if(M5Name != 0) {
terminal->Write(M5Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM5(buf);
}
if(M6Name != 0) {
terminal->Write(M6Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM6(buf);
}
if(M7Name != 0) {
terminal->Write(M7Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM7(buf);
}
if(M8Name != 0) {
terminal->Write(M8Name, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM8(buf);
}
if(Comments != 0) {
terminal->Write(Comments, p->XPos(), p->YOffset(1));
terminal->Write(" -> ");
terminal->GetString(cbuf);
strdb.SetCM(cbuf);
}
terminal->Write("(A)-Abort (C)-Change, Any other key to accept entry",
p->XPos(), p->YOffset(2));
int c = terminal->GetChar();
switch(c) {
case 'c': case 'C':
terminal->ClearScreen();
p->SetXY(0, 0);
ChangeObject(strdb, p, 1);
break;
case 'a': case 'A':
return;
default:
break;
}
FAU addr = strdb.AddObject(0); // Write the object to the file
if(!addr) {
terminal->Write("Could not add item to database",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
return;
}
terminal->Write("Item was added to the database",
p->XPos(), p->YOffset(2));
terminal->Write("Add another (y/n)", p->XPos(), p->YOffset(2));
if(terminal->GetYesNo()) Add(); else return;
}
void FindBy(const char *MemberName, StrDBItem item)
{
if(MemberName == 0) return;
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
char buf[KeyBuf];
unsigned offset = 0;
StrDB strdb(DB);
terminal->Write("Enter complete string or use ", p->XPos(), p->YPos());
terminal->Write(WildCard);
terminal->Write(" for a wild card.");
terminal->Write(MemberName, p->XPos(), p->YOffset(2));
terminal->Write(" -> ");
terminal->GetString(buf);
UString str(buf);
offset = str.Find(WildCard, offset); // Look for wild card character
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(1));
delete p;
return;
}
if(offset == UString::NoMatch) { // No wild cards found
strdb.SetKM(buf);
StrDBSearch(strdb, item, str, p);
delete p; // Free the Coord pointer
return;
}
StrDBSearch(strdb, item, str, p, WildCard);
delete p; // Free the Coord pointer
}
void FindByKeyName()
{
FindBy(KeyName, KEYMEMBER);
}
void FindByM2Name()
{
FindBy(M2Name, M2NAME);
}
void FindByM3Name()
{
FindBy(M3Name, M3NAME);
}
void FindByM4Name()
{
FindBy(M4Name, M4NAME);
}
void FindByM5Name()
{
FindBy(M5Name, M5NAME);
}
void FindByM6Name()
{
FindBy(M6Name, M6NAME);
}
void FindByM7Name()
{
FindBy(M7Name, M7NAME);
}
void FindByM8Name()
{
FindBy(M8Name, M8NAME);
}
void FindByComments()
{
FindBy(Comments, COMMENTS);
}
void Change()
{
if(KeyName == 0) return;
if(!AdminRights) {
terminal->ClearScreen();
terminal->Write("You do not have Admin User Privileges", 0, 1);
terminal->AnyKey(0, 2);
return;
}
Coords *p = new Coords(0, 0);
char buf[KeyBuf];
terminal->ClearScreen();
terminal->Write(KeyName, p->XPos(), p->YPos());
terminal->Write(" to change -> ");
terminal->GetString(buf);
StrDB strdb(DB);
strdb.SetKM(buf);
FAU addr = strdb.FindObject();
if(!addr) {
terminal->Write("Could not find: ", p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free Coords pointer
return;
}
ChangeObject(strdb, p);
delete p; // Free Coords pointer
}
void ChangeObject(StrDB &strdb, Coords *p, int adding)
{
char buf[KeyBuf];
char cbuf[CBuf];
// Buffer the object's data to allow changes to be canceled
StrDB ob;
ob.Copy(strdb);
FAU addr;
StrDB changed(DB); // Temp buffer used to record changes
char *prompt = "Press the number/letter of your selection -> ";
int c, x, y, x_prev, y_prev, x_prompt, y_prompt;
x_prev = p->XPos(); y_prev = p->YPos();
while(1) {
p->SetXY(x_prev, y_prev);
terminal->Write("(C) Cancel change", p->XPos(), p->YOffset(2));
if(adding) {
if(KeyName != 0) {
terminal->Write("(0) ", p->XPos(), p->YOffset(1));
terminal->Write(KeyName); terminal->Write(" = ");
terminal->Write(strdb.GetKM());
terminal->ClearLine();
}
}
else {
if(KeyName != 0) {
terminal->Write("(-) ", p->XPos(), p->YOffset(1));
terminal->Write(KeyName); terminal->Write(" = ");
terminal->Write(strdb.GetKM());
terminal->ClearLine();
}
}
if(M2Name != 0) {
terminal->Write("(1) ", p->XPos(), p->YOffset(1));
terminal->Write(M2Name); terminal->Write(" = ");
terminal->Write(strdb.GetM2());
terminal->ClearLine();
}
if(M3Name != 0) {
terminal->Write("(2) ", p->XPos(), p->YOffset(1));
terminal->Write(M3Name); terminal->Write(" = ");
terminal->Write(strdb.GetM3());
terminal->ClearLine();
}
if(M4Name != 0) {
terminal->Write("(3) ", p->XPos(), p->YOffset(1));
terminal->Write(M4Name); terminal->Write(" = ");
terminal->Write(strdb.GetM4());
terminal->ClearLine();
}
if(M5Name != 0) {
terminal->Write("(4) ", p->XPos(), p->YOffset(1));
terminal->Write(M5Name); terminal->Write(" = ");
terminal->Write(strdb.GetM5());
terminal->ClearLine();
}
if(M6Name != 0) {
terminal->Write("(5) ", p->XPos(), p->YOffset(1));
terminal->Write(M6Name); terminal->Write(" = ");
terminal->Write(strdb.GetM6());
terminal->ClearLine();
}
if(M7Name != 0) {
terminal->Write("(6) ", p->XPos(), p->YOffset(1));
terminal->Write(M7Name); terminal->Write(" = ");
terminal->Write(strdb.GetM7());
terminal->ClearLine();
}
if(M8Name != 0) {
terminal->Write("(7) ", p->XPos(), p->YOffset(1));
terminal->Write(M8Name); terminal->Write(" = ");
terminal->Write(strdb.GetM8());
terminal->ClearLine();
}
if(Comments != 0) {
terminal->Write("(8) ", p->XPos(), p->YOffset(1));
terminal->Write(Comments); terminal->Write(" = ");
terminal->Write(strdb.GetCM());
terminal->ClearLine();
}
terminal->Write("(A) Accept changes", p->XPos(), p->YOffset(1));
terminal->Write(prompt, p->XPos(), p->YOffset(2));
x_prompt = p->XPos() + strlen(prompt);
y_prompt = p->YPos();
x = p->XPos();
y = p->YPos() + 2;
c = terminal->GetChar();
switch(c) {
case 'C': case 'c':
strdb.Copy(ob);
return;
case '0':
// User not allowed to change name unless adding a new object
if(!adding) break;
if(KeyName != 0) {
terminal->Write(KeyName, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetKM(buf);
addr = strdb.FindObject();
if(addr) {
terminal->Write("Entry already exists!", x, y+1);
terminal->AnyKey();
terminal->ClearLine(x, y+1);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
break;
}
strdb.SetKM(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '1':
if(M2Name != 0) {
terminal->Write(M2Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM2(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '2':
if(M3Name != 0) {
terminal->Write(M3Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM3(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '3':
if(M4Name != 0) {
terminal->Write(M4Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM4(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '4':
if(M5Name != 0) {
terminal->Write(M5Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM5(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '5':
if(M6Name != 0) {
terminal->Write(M6Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM6(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '6':
if(M7Name != 0) {
terminal->Write(M7Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM7(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '7':
if(M8Name != 0) {
terminal->Write(M8Name, x, y);
terminal->Write(" -> ");
terminal->GetString(buf);
strdb.SetM8(buf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case '8':
if(Comments != 0) {
terminal->Write(Comments, x, y);
terminal->Write(" -> ");
terminal->GetString(cbuf);
strdb.SetCM(cbuf);
terminal->ClearLine(x, y);
terminal->MoveCursor(x_prev, y_prev);
}
break;
case 'A': case 'a':
if(adding) return; // New object, no need to reallocate space
if(strdb.FullCompare(ob)) return; // The object has not changed
changed.Copy(strdb); // Make a copy of the changes
// Remove the original object
strdb.DeleteObject();
changed.AddObject(0); // Add the changed object back to the database
return;
default:
break;
}
}
}
void DisplayObject(StrDB &strdb, Coords *p)
// Display's the complete object with all details.
{
if(KeyName != 0) {
terminal->Write(KeyName, p->XPos(), p->YPos());
terminal->Write(" = ");
terminal->Write(strdb.GetKM());
}
if(M2Name != 0) {
terminal->Write(M2Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM2());
}
if(M3Name != 0) {
terminal->Write(M3Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM3());
}
if(M4Name != 0) {
terminal->Write(M4Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM4());
}
if(M5Name != 0) {
terminal->Write(M5Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM5());
}
if(M6Name != 0) {
terminal->Write(M6Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM6());
}
if(M7Name != 0) {
terminal->Write(M7Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM7());
}
if(M8Name != 0) {
terminal->Write(M8Name, p->XPos(), p->YOffset(1));
terminal->Write(" = ");
terminal->Write(strdb.GetM8());
}
if(Comments != 0) {
terminal->Write(Comments, p->XPos(), p->YOffset(1));
terminal->Write(": ");
terminal->Write(strdb.GetCM());
}
}
void DisplayString(const char *s)
{
int len = strlen(s);
int offset = StringOffset;
char *buf = new char[len + 1];
buf[len] = '\0';
strcpy(buf, s);
if(len < StringOffset) offset = len;
for(int i = 0; i < offset; i++)
terminal->Write(buf[i]);
delete[] buf;
}
void LineByLine(StrDB &strdb, Coords *p)
// Display objects line by line with partial details
{
int x = p->XPos();
if(KeyName != 0) {
terminal->MoveCursor(p->XPos(), p->YPos());
DisplayString(strdb.GetKM());
}
if(M2Name != 0) {
terminal->MoveCursor(p->XOffset(StringOffset+1), p->YPos());
DisplayString(strdb.GetM2());
}
if(M3Name != 0) {
terminal->MoveCursor(p->XOffset(StringOffset+1), p->YPos());
DisplayString(strdb.GetM3());
}
if(M4Name != 0) {
terminal->MoveCursor(p->XOffset(StringOffset+1), p->YPos());
DisplayString(strdb.GetM4());
}
if(M5Name != 0) {
terminal->MoveCursor(p->XOffset(StringOffset+1), p->YPos());
DisplayString(strdb.GetM5());
}
int i = 0;
terminal->MoveCursor(0, p->YOffset(1));
while (i++ < terminal->MaxCols()-1) terminal->Write('-');
p->SetX(x);
}
void Version()
{
printf("\n%s program version %.3f\n", ProgramName, VersionNumber);
exit(0);
}
void ExportToASCII()
{
char buf[CBuf];
char *FileName;
const char dchar = '\t'; // Text delimiter
const char filter = '\t'; // Filter tabs
const char *Fill = "None"; // Fill character string
terminal->ClearScreen();
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.", 0, 1);
terminal->AnyKey(0, 2);
return;
}
Coords *p = new Coords(0, 0);
terminal->Write("Export database to ASCII file delimited by tabs",
p->XPos(), p->YPos());
terminal->Write("Enter file name to export to: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(2));
if(!yn) {
delete p;
delete[] tmp;
return;
}
}
FileName = tmp;
delete[] tmp;
ofstream stream(FileName, ios::out); // Open file and truncate it
terminal->Write("Exporting database to: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
StrDB strdb(DB);
// Write the item bar to the file first
if(KeyName != 0) {
ASPrint(KeyName, stream, strlen(KeyName));
stream << dchar;
}
if(M2Name != 0) {
ASPrint(M2Name, stream, strlen(M2Name));
stream << dchar;
}
if(M3Name != 0) {
ASPrint(M3Name, stream, strlen(M3Name));
stream << dchar;
}
if(M4Name != 0) {
ASPrint(M4Name, stream, strlen(M4Name));
stream << dchar;
}
if(M5Name != 0) {
ASPrint(M5Name, stream, strlen(M5Name));
stream << dchar;
}
if(M6Name != 0) {
ASPrint(M6Name, stream, strlen(M6Name));
stream << dchar;
}
if(M7Name != 0) {
ASPrint(M7Name, stream, strlen(M7Name));
stream << dchar;
}
if(M8Name != 0) {
ASPrint(M8Name, stream, strlen(M8Name));
stream << dchar;
}
if(Comments != 0) {
ASPrint(Comments, stream, strlen(Comments));
}
stream << asLineFeed;
int exports = 0;
LoadIndexKeys();
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
strdb.ReadObject(dllistptr->Data.object_address);
if(KeyName != 0) {
ASPrint(strdb.GetKM(), filter, stream, strlen(strdb.GetKM()));
stream << dchar;
}
if(M2Name != 0) {
if(!*strdb.GetM2()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM2(), filter, stream, strlen(strdb.GetM2()));
stream << dchar;
}
if(M3Name != 0) {
if(!*strdb.GetM3()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM3(), filter, stream, strlen(strdb.GetM3()));
stream << dchar;
}
if(M4Name != 0) {
if(!*strdb.GetM4()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM4(), filter, stream, strlen(strdb.GetM4()));
stream << dchar;
}
if(M5Name != 0) {
if(!*strdb.GetM5()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM5(), filter, stream, strlen(strdb.GetM5()));
stream << dchar;
}
if(M6Name != 0) {
if(!*strdb.GetM6()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM6(), filter, stream, strlen(strdb.GetM6()));
stream << dchar;
}
if(M7Name != 0) {
if(!*strdb.GetM7()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM7(), filter, stream, strlen(strdb.GetM7()));
stream << dchar;
}
if(M8Name != 0) {
if(!*strdb.GetM8()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetM8(), filter, stream, strlen(strdb.GetM8()));
stream << dchar;
}
if(Comments != 0) {
if(!*strdb.GetCM()) ASPrint(Fill, stream, strlen(Fill));
else ASPrint(strdb.GetCM(), filter, stream, strlen(strdb.GetCM()));
}
stream << asLineFeed;
exports++;
dllistptr = dllistptr->GetNext();
}
dllist->Clear();
terminal->Write("Exported ", p->XPos(), p->YOffset(2));
terminal->Write(exports);
terminal->Write(" items.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
stream.close();
}
void ImportFromASCII()
{
if(KeyName == 0) return;
if(!AdminRights) {
terminal->ClearScreen();
terminal->Write("You do not have Admin User Privileges", 0, 1);
terminal->AnyKey(0, 2);
return;
}
char buf[CBuf];
char words[MAXWORDS][MAXWORDLENGTH];
int num;
const int MaxLine = 512;
char LineBuffer[MaxLine];
char *sbuf;
char *FileName;
const char dchar = '\t'; // Text delimiter
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
terminal->Write("Importing database from ASCII file delimited by tabs",
p->XPos(), p->YPos());
terminal->Write("Enter file name to import from: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(!VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" does not exists.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
FileName = tmp;
ifstream stream(FileName, ios::in|ios::nocreate);
terminal->Write("Importing database from: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
if(!stream) { // Could not open the stream
terminal->Write("Could not open file: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete[] tmp;
delete p; // Free the Coords pointer
return;
}
terminal->Write("Importing...", p->XPos(), p->YOffset(2));
ChSNode *listptr; // Linked list node pointer
ChSList list; // Linked list
while(!stream.eof())
{
// Read in file line by line
stream.getline(LineBuffer, MaxLine);
// Allocate memory for temporary holding buffer
sbuf = new char[strlen(LineBuffer)+1];
// Copy contents of the array to temporary holding buffer
strcpy(sbuf, LineBuffer);
// Load file data into singly-linked list
listptr = list.Store(sbuf);
if(!listptr) { // Out of memory
stream.close();
delete[] sbuf;
list.Clear();
return;
}
}
stream.close();
delete[] sbuf;
StrDB strdb(DB);
StrDB strdba(DB);
StrDB ob(DB);
int linecount = 0;
int imports = 0;
int updates = 0;
int updateall = 0;
int ObjectItems = 1; // Number of class data members
int x_prev, y_prev, c;
FAU addr;
// Calculate the number of object items
if(M2Name != 0) ObjectItems++;
if(M3Name != 0) ObjectItems++;
if(M4Name != 0) ObjectItems++;
if(M5Name != 0) ObjectItems++;
if(M6Name != 0) ObjectItems++;
if(M7Name != 0) ObjectItems++;
if(M8Name != 0) ObjectItems++;
if(Comments != 0) ObjectItems++;
listptr = list.GetFront();
while(!list.IsHeader(listptr)) {
if(parse(listptr->Data, words, &num, dchar) == 1) {
terminal->Write("Parse error!", p->XPos(), p->YOffset(2));
break;
}
linecount++;
if(num != ObjectItems && (num != 0 && num != 1)) {
x_prev = p->XPos(); y_prev = p->YPos();
terminal->Write("Error in ", p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->Write(" import file!");
if(num > ObjectItems)
terminal->Write("To many items on line: ", p->XPos(), p->YOffset(2));
if(num < ObjectItems)
terminal->Write("Not enough items on line: ",
p->XPos(), p->YOffset(2));
terminal->Write(linecount);
terminal->Write("(X)-Exit, Any other key to continue",
p->XPos(), p->YOffset(2));
c = terminal->GetChar();
switch(c) {
case 'x': case 'X':
delete p; // Free the Coords pointer
delete[] tmp;
list.Clear();
return;
default:
break;
}
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-4);
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
}
if(num == ObjectItems && *words[0] != 0) {
strdb.SetKM(words[0]);
if(M2Name != 0) strdb.SetM2(words[1]);
if(M3Name != 0) strdb.SetM3(words[2]);
if(M4Name != 0) strdb.SetM4(words[3]);
if(M5Name != 0) strdb.SetM5(words[4]);
if(M6Name != 0) strdb.SetM6(words[5]);
if(M7Name != 0) strdb.SetM7(words[6]);
if(M8Name != 0) strdb.SetM8(words[7]);
if(Comments != 0) strdb.SetCM(words[8]);
strdba.SetKM(strdb.GetKM());
addr = strdba.FindObject();
if(addr) {
x_prev = p->XPos(); y_prev = p->YPos();
if(updateall == 0) {
terminal->Write(strdb.GetKM(), p->XPos(), p->YOffset(2));
terminal->Write(" entry already exists.");
terminal->Write("(U)-Update, (A)-Update all, (X)-Exit",
p->XPos(), p->YOffset(2));
terminal->Write(", Any other key to continue");
c = terminal->GetChar();
}
if(updateall == 1) c = 'a';
switch(c) {
case 'a': case 'A':
updateall = 1;
updates++;
ob.Copy(strdba);
if(strdb.FullCompare(ob)) break; // The object has not changed
ob.DeleteObject();
strdb.AddObject(0);
break;
case 'u': case 'U':
updates++;
ob.Copy(strdba);
if(strdb.FullCompare(ob)) break; // The object has not changed
ob.DeleteObject();
strdb.AddObject(0);
break;
case 'x': case 'X':
delete p; // Free the Coords pointer
delete[] tmp;
list.Clear();
return;
default:
break;
}
if(updateall == 1) {
p->SetXY(x_prev, y_prev);
terminal->ClearLine(x_prev, y_prev+2);
terminal->ClearLine(x_prev, y_prev+4);
terminal->Write("Updating entry for: ", p->XPos(), p->YOffset(2));
terminal->Write(strdb.GetKM(), p->XPos(), p->YOffset(2));
Sleep((clock_t)1);
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
terminal->MoveCursor(x_prev, y_prev);
}
else {
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
terminal->MoveCursor(x_prev, y_prev);
}
}
else {
// Ensure that the template does not get added to the file
if(CaseICmp(KeyName, words[0]) != 0) {
FAU addr = strdb.AddObject(0); // Write the object to the file
imports++;
if(!addr) {
x_prev = p->XPos(); y_prev = p->YPos();
terminal->Write("Could not add:", p->XPos(), p->YOffset(2));
terminal->Write(strdb.GetKM());
terminal->Write(" to database");
terminal->AnyKey(p->XPos(), p->YOffset(2));
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
imports--;
}
}
}
}
listptr = listptr->GetNext();
}
terminal->Write("Imported ", p->XPos(), p->YOffset(2));
terminal->Write(imports);
terminal->Write(" items.");
if(updates) {
terminal->Write("Updated ", p->XPos(), p->YOffset(2));
terminal->Write(updates);
terminal->Write(" items.");
}
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
delete[] tmp;
list.Clear();
}
void BackUp()
{
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.", 0, 1);
terminal->AnyKey(0, 2);
return;
}
char buf[CBuf];
char *FileName;
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
terminal->Write("Backing up the database to another file",
p->XPos(), p->YPos());
terminal->Write("Enter new file name to create: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" already exists.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
FileName = tmp;
POD newdb(FileName, FileName);
int items = 0;
StrDB strdb(&newdb);
StrDB strdb_old(DB);
FAU oa; // Object Address
VBHeader vb; // Variable Block Header
ObjectHeader oh; // Object Header
FAU vbdfileEOF = DB->OpenDatabase()->GetEOF();
FAU addr = 0;
addr = DB->OpenDatabase()->FindFirstVB(addr); // Search the entire file
if(addr == 0) return; // No variable blocks found in file
while(1) {
if(addr >= vbdfileEOF) break;
DB->OpenDatabase()->Read(&vb, sizeof(VBHeader), addr);
if(vb.CkWord == CheckWord) {
if((__SBYTE__)vb.Status == NormalVB) {
oa = addr + sizeof(VBHeader);
DB->OpenDatabase()->Read(&oh, sizeof(ObjectHeader), oa);
if(oh.ClassID == strdb.GetClassID()) {
strdb_old.ReadObject(oa);
strdb.Copy(strdb_old);
strdb.AddObject(0);
items++;
}
}
addr = addr + vb.Length; // Goto the next variable block
}
else {
addr = DB->OpenDatabase()->VBSearch(addr);
if(!addr) break;
}
}
terminal->Write("Backed up ",
p->XPos(), p->YOffset(2));
terminal->Write(items);
terminal->Write(" objects to ");
terminal->Write(tmp);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete[] tmp;
delete p;
}
void Merge()
{
if(!AdminRights) {
terminal->ClearScreen();
terminal->Write("You do not have Admin User Privileges", 0, 1);
terminal->AnyKey(0, 2);
return;
}
char buf[CBuf];
char *FileName;
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
terminal->Write("Merging the contents of another database",
p->XPos(), p->YPos());
terminal->Write("Enter file name to merge: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(!VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" does not exists.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
FileName = tmp;
POD *newdb = new POD(FileName, FileName, ROMode);
StrDB strdb(newdb);
StrDB strdba(DB);
StrDB ob(DB);
FAU addr;
FAU existing;
int x_prev, y_prev, c;
int imports = 0;
int updates = 0;
int updateall = 0;
FAU oa; // Object Address
VBHeader vb; // Variable Block Header
ObjectHeader oh; // Object Header
FAU vbdfileEOF = newdb->OpenDatabase()->GetEOF();
addr = 0;
addr = newdb->OpenDatabase()->FindFirstVB(addr); // Search the entire file
if(addr == 0) {
terminal->Write("No variable blocks found in file: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
terminal->Write("Merging...", p->XPos(), p->YOffset(2));
while(1) {
if(addr >= vbdfileEOF) break;
newdb->OpenDatabase()->Read(&vb, sizeof(VBHeader), addr);
if(vb.CkWord == CheckWord) {
if((__SBYTE__)vb.Status == NormalVB) {
oa = addr + sizeof(VBHeader);
newdb->OpenDatabase()->Read(&oh, sizeof(ObjectHeader), oa);
if(oh.ClassID == strdb.GetClassID()) {
strdb.ReadObject(oa);
strdba.SetKM(strdb.GetKM());
existing = strdba.FindObject();
if(existing) {
x_prev = p->XPos(); y_prev = p->YPos();
if(updateall == 0) {
terminal->Write(strdb.GetKM(), p->XPos(), p->YOffset(2));
terminal->Write(" entry already exists.");
terminal->Write("(U)-Update, (A)-Update all, (X)-Exit",
p->XPos(), p->YOffset(2));
terminal->Write(", Any other key to continue");
c = terminal->GetChar();
}
if(updateall == 1) c = 'a';
switch(c) {
case 'a': case 'A':
updateall = 1;
updates++;
ob.Copy(strdb);
if(strdb.FullCompare(ob)) break; // The object has not changed
ob.DeleteObject();
ob.Copy(strdb);
ob.AddObject(0);
break;
case 'u': case 'U':
updates++;
ob.Copy(strdb);
if(strdb.FullCompare(ob)) break; // The object has not changed
ob.DeleteObject();
ob.Copy(strdb);
ob.AddObject(0);
break;
case 'x': case 'X':
delete newdb;
delete p;
delete[] tmp;
return;
default:
break;
}
if(updateall == 1) {
p->SetXY(x_prev, y_prev);
terminal->ClearLine(x_prev, y_prev+1);
terminal->ClearLine(x_prev, y_prev+4);
terminal->Write("Updating entry for: ",
p->XPos(), p->YOffset(2));
terminal->Write(strdb.GetKM(), p->XPos(), p->YOffset(2));
Sleep((clock_t)1);
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
terminal->MoveCursor(x_prev, y_prev);
}
else {
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
terminal->MoveCursor(x_prev, y_prev);
}
}
else {
strdba.Copy(strdb);
FAU rvaddr = strdba.AddObject(0); // Write the object to the file
imports++;
if(!rvaddr) {
x_prev = p->XPos(); y_prev = p->YPos();
terminal->Write("Could not add:", p->XPos(), p->YOffset(2));
terminal->Write(ob.GetKM());
terminal->Write(" to database");
terminal->AnyKey(p->XPos(), p->YOffset(2));
terminal->ClearLine(p->XPos(), p->YPos());
terminal->ClearLine(p->XPos(), p->YPos()-2);
p->SetXY(x_prev, y_prev);
imports--;
}
}
}
}
addr = addr + vb.Length; // Goto the next variable block
}
else {
addr = newdb->OpenDatabase()->VBSearch(addr);
if(!addr) break;
}
}
terminal->Write("Imported ", p->XPos(), p->YOffset(2));
terminal->Write(imports);
terminal->Write(" items.");
if(updates) {
terminal->Write("Updated ", p->XPos(), p->YOffset(2));
terminal->Write(updates);
terminal->Write(" items.");
}
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete newdb;
delete p;
delete[] tmp;
}
void CreateTemplate()
{
char buf[CBuf];
char *FileName;
const char dchar = '\t'; // Text delimiter
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
terminal->Write("Creating template file delimited by tabs",
p->XPos(), p->YPos());
terminal->Write("Enter file name to create: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(2));
if(!yn) {
delete p;
delete[] tmp;
return;
}
}
FileName = tmp;
delete[] tmp;
ofstream stream(FileName, ios::out); // Open file and truncate it
terminal->Write("Creating template file: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(2));
terminal->Write(FileName);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
if(KeyName != 0) {
ASPrint(KeyName, stream, strlen(KeyName));
stream << dchar;
}
if(M2Name != 0) {
ASPrint(M2Name, stream, strlen(M2Name));
stream << dchar;
}
if(M3Name != 0) {
ASPrint(M3Name, stream, strlen(M3Name));
stream << dchar;
}
if(M4Name != 0) {
ASPrint(M4Name, stream, strlen(M4Name));
stream << dchar;
}
if(M5Name != 0) {
ASPrint(M5Name, stream, strlen(M5Name));
stream << dchar;
}
if(M6Name != 0) {
ASPrint(M6Name, stream, strlen(M6Name));
stream << dchar;
}
if(M7Name != 0) {
ASPrint(M7Name, stream, strlen(M7Name));
stream << dchar;
}
if(M8Name != 0) {
ASPrint(M8Name, stream, strlen(M8Name));
stream << dchar;
}
if(Comments != 0) {
ASPrint(Comments, stream, strlen(Comments));
}
stream << asLineFeed;
terminal->Write("Finished", p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
stream.close();
}
void CompareIndexFile()
{
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
if(!DB->UsingIndex()) {
terminal->Write("No index is being used for this database.",
p->XPos(), p->YPos());
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
terminal->Write("Comparing the index file to the data file...",
p->XPos(), p->YPos());
StrDB strdb(DB);
int rv = strdb.CompareIndex();
if(!rv) {
terminal->Write("The index file does not match the data file!",
p->XPos(), p->YOffset(2));
terminal->Write("The index file needs to be rebuilt.",
p->XPos(), p->YOffset(1));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
terminal->Write("The index file checks good.",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
void RebuildIndexFile()
{
char buf[CBuf];
char *FileName;
terminal->ClearScreen();
Coords *p = new Coords(0, 0);
if(!DB->UsingIndex()) {
terminal->Write("No index is being used for this database.",
p->XPos(), p->YPos());
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
terminal->Write("Rebuilding the index file for this database.",
p->XPos(), p->YPos());
terminal->Write("Enter new file name to create: ",
p->XPos(), p->YOffset(2));
terminal->GetString(buf);
char *tmp = new char[strlen(buf)+1];
tmp[strlen(buf)] = '\0';
strcpy(tmp, buf);
if(VBDFile::Exists(tmp)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(tmp);
terminal->Write(" already exists.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
terminal->Write("Rebuilding the index file... ",
p->XPos(), p->YOffset(2));
StrDB strdb(DB);
int rv = strdb.RebuildIndexFile(tmp);
if(!rv) {
terminal->Write("The index file was not rebuilt!",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
return;
}
terminal->Write("The index file was rebuilt.",
p->XPos(), p->YOffset(2));
terminal->Write("A new index file named ",
p->XPos(), p->YOffset(1));
terminal->Write(tmp);
terminal->Write(" was created.");
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p;
delete[] tmp;
}
void StrDBSearch(StrDB &strdb, StrDBItem item, UString &str,
Coords *p, const char *wildcard)
{
terminal->Write("Searching for ", p->XPos(), p->YOffset(2));
terminal->Write(str.c_str());
int offset;
offset = ObjectsFound = 0;
if(wildcard != 0) {
while(1) { // Remove the wild card characters from the string
offset = str.Find(wildcard, offset);
if (offset == UString::NoMatch) break;
str.DeleteAt(offset, strlen(wildcard));
offset++;
}
}
// Ensure that the memory buffers and the file data
// stay in sync during multiple file access.
DB->Index()->TestTree();
dllist->Clear();
if(wildcard != 0)
BtreeSearch(DB->Index(), item, strdb, str, 1);
else
BtreeSearch(DB->Index(), item, strdb, str);
if(ObjectsFound == 0) {
terminal->Write("No matches found.", p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(1));
return;
}
if(ObjectsFound > 1) { // Found multiple matches
terminal->Write("Found ", p->XPos(), p->YOffset(2));
terminal->Write(ObjectsFound);
terminal->Write(" matching.");
terminal->AnyKey(p->XPos(), p->YOffset(1));
}
else {
terminal->Write("Found matching entry for: ", p->XPos(), p->YOffset(2));
terminal->Write(str.c_str());
terminal->AnyKey(p->XPos(), p->YOffset(1));
}
// Display all the matches
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
terminal->ClearScreen();
p->SetXY(0, 0);
strdb.ReadObject(dllistptr->Data.object_address);
DisplayObject(strdb, p);
terminal->Write("(C)-Change, (D)-Delete, (P)-Print, (X)-Exit",
p->XPos(), p->YOffset(2));
terminal->Write(", Any other key to continue");
int c = terminal->GetChar();
switch(c) {
case 'c': case 'C':
terminal->ClearScreen();
p->SetXY(0, 0);
strdb.ReadObject(dllistptr->Data.object_address);
ChangeObject(strdb, p);
break;
case 'd': case 'D': {
int yn = terminal->YesNo("Are you sure you want to delete (y/n)",
p->XPos(), p->YOffset(2));
if(!yn) break;
strdb.ReadObject(dllistptr->Data.object_address);
strdb.DeleteObject();
break;
}
case 'p': case 'P':
strdb.ReadObject(dllistptr->Data.object_address);
p->YOffset(1);
PrintObject(strdb, p);
break;
case 'x': case 'X':
dllist->Clear(); // Free dllist memory
return;
default:
break;
}
dllistptr = dllistptr->GetNext();
}
dllist->Clear(); // Free dllist memory
}
int PrintPSItemBar(ofstream &stream, PostScriptDrv &psdrv,
int x_offset, int char_offset, int cell_len)
{
if(KeyName != 0) {
psdrv.PrintLine((char *)KeyName, cell_len, stream);
x_offset += char_offset;
}
if(M2Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M2Name, cell_len, stream);
x_offset += char_offset;
}
if(M3Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M3Name, cell_len, stream);
x_offset += char_offset;
}
if(M4Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M4Name, cell_len, stream);
x_offset += char_offset;
}
if(M5Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M5Name, cell_len, stream);
x_offset += char_offset;
}
if(M6Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M6Name, cell_len, stream);
x_offset += char_offset;
}
if(M7Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M7Name, cell_len, stream);
x_offset += char_offset;
}
if(M8Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)M8Name, cell_len, stream);
x_offset += char_offset;
}
if(Comments != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine((char *)Comments, cell_len, stream);
x_offset += char_offset;
}
return x_offset;
}
void PostScriptPrint()
{
Coords *p = new Coords(0, 0);
terminal->ClearScreen();
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
return;
}
char buf[CBuf];
int i;
// Setup the default values for user configurable PostScript parameters
int cell_len = 19;
double font_size = 7;
int orientation = 1;
const int DocNameLen = 255;
char psDocName[DocNameLen];
for(i = 0; i < DocNameLen; i++) psDocName[i] = 0;
strcpy(psDocName, ProgramName);
PostScriptDrv::PSPaperSizes paper_code = PostScriptDrv::LETTER_SIZE;
PostScriptDrv::PSFonts item_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
PostScriptDrv::PSFonts cell_font = PostScriptDrv::COURIER;
// Load the PostScript configuration from the config file
char *CurrentCfgFile;
char *CfgFile;
Config *CfgData = new Config;
// Look for CfgFile name in environment
if((CurrentCfgFile = getenv(EnvSetting)) == 0)
CfgFile = (char *)DefaultCfgFile;
else
CfgFile = CurrentCfgFile;
int FileStatus = CfgData->Load((char *)CfgFile);
if(FileStatus) { // Found a valid config file
// *********************************************************** //
// Add all PostScript config file entries here
// *********************************************************** //
int int_val = 0;
double dfp_val = 0;
char *str_val = 0;
int_val = CfgData->GetIntValue("CellLength");
if(int_val > 0) cell_len = int_val;
dfp_val = CfgData->GetDFPValue("FontSize");
if(dfp_val > 0) font_size = dfp_val;
str_val = CfgData->GetStrValue("Orientation");
if(str_val != 0) {
if(strcmp(str_val, "PORTRAIT") == 0) orientation = 0;
str_val = 0;
}
str_val = CfgData->GetStrValue("PaperSize");
if(str_val != 0) {
if(strcmp(str_val, "LETTER") == 0)
paper_code = PostScriptDrv::LETTER_SIZE;
if(strcmp(str_val, "LEGAL") == 0)
paper_code = PostScriptDrv::LEGAL_SIZE;
if(strcmp(str_val, "TABLOID") == 0)
paper_code = PostScriptDrv::TABLOID_SIZE;
if(strcmp(str_val, "A3") == 0) paper_code = PostScriptDrv::A3_SIZE;
if(strcmp(str_val, "A4") == 0) paper_code = PostScriptDrv::A4_SIZE;
str_val = 0;
}
str_val = CfgData->GetStrValue("ItemBarFont");
if(str_val != 0) {
if(strcmp(str_val, "COURIER") == 0)
item_font = PostScriptDrv::COURIER;
if(strcmp(str_val, "COURIER_BOLD") == 0)
item_font = PostScriptDrv::COURIER_BOLD;
if(strcmp(str_val, "COURIER_OBLIQUE") == 0)
item_font = PostScriptDrv::COURIER_OBLIQUE;
if(strcmp(str_val, "COURIER_BOLD_OBLIQUE") == 0)
item_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
str_val = 0;
}
str_val = CfgData->GetStrValue("CellFont");
if(str_val != 0) {
if(strcmp(str_val, "COURIER") == 0)
cell_font = PostScriptDrv::COURIER;
if(strcmp(str_val, "COURIER_BOLD") == 0)
cell_font = PostScriptDrv::COURIER_BOLD;
if(strcmp(str_val, "COURIER_OBLIQUE") == 0)
cell_font = PostScriptDrv::COURIER_OBLIQUE;
if(strcmp(str_val, "COURIER_BOLD_OBLIQUE") == 0)
cell_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
}
str_val = CfgData->GetStrValue("psDocumentName");
if(str_val != 0) {
for(i = 0; i < DocNameLen; i++) psDocName[i] = 0;
strcpy(psDocName, str_val);
}
// *********************************************************** //
}
CfgData->UnLoad(); // Unload the Config file from memory
for(i = 0; i < CBuf; i++) buf[i] = 0;
terminal->Write("Enter file name to print to: ",
p->XPos(), p->YPos());
terminal->GetString(buf);
if(VBDFile::Exists(buf)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(2));
if(!yn) {
delete p;
return;
}
}
ofstream stream(buf, ios::out); // Open file and truncate it
terminal->Write("Printing to: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
terminal->Write("Printing...", p->XPos(), p->YOffset(2));
PostScriptDrv psdrv;
psdrv.Copies(1);
// Setup the PostScript driver
psdrv.SetPaperSize(paper_code);
psdrv.SetFont(cell_font, font_size);
psdrv.UseHeader();
if(orientation == 1) psdrv.LandScapeMode();
psdrv.SetDocumentName(psDocName);
char time_buf[255]; // Buffer used to hold time/date string
GetSystemTime(time_buf);
psdrv.SetDateString(time_buf);
psdrv.DocumentSetup();
psdrv.Prologue(stream);
psdrv.MediaSetup(stream);
StrDB strdb(DB);
int char_offset = int((cell_len + 1) * psdrv.CharWidth());
int x_offset;
if(orientation == 0)
x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
else
x_offset = PRINTABLE_OFFSET_X;
int lines = 4;
psdrv.StartPage(psdrv.page_count + 1, stream);
psdrv.row = psdrv.StartY();
psdrv.MoveTo(stream, psdrv.StartX(), psdrv.row);
psdrv.ChangeFont(stream, item_font, font_size);
x_offset = PrintPSItemBar(stream, psdrv, x_offset, char_offset, cell_len);
psdrv.ChangeFont(stream, cell_font, font_size);
int line_points;
if(orientation == 0)
line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
else
line_points = x_offset - PRINTABLE_OFFSET_X;
psdrv.row -= (int)psdrv.FontSize();
lines++;
psdrv.drawThickLine(stream, line_points, psdrv.StartX(), psdrv.row);
psdrv.row -= THICK_LINE_WIDTH + psdrv.FontSize();
lines++;
LoadIndexKeys();
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
strdb.ReadObject(dllistptr->Data.object_address);
if(orientation == 0)
x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
else
x_offset = PRINTABLE_OFFSET_X;
if(KeyName != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetKM(), cell_len, stream);
x_offset += char_offset;
}
if(M2Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM2(), cell_len, stream);
x_offset += char_offset;
}
if(M3Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM3(), cell_len, stream);
x_offset += char_offset;
}
if(M4Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM4(), cell_len, stream);
x_offset += char_offset;
}
if(M5Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM5(), cell_len, stream);
x_offset += char_offset;
}
if(M6Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM6(), cell_len, stream);
x_offset += char_offset;
}
if(M7Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM7(), cell_len, stream);
x_offset += char_offset;
}
if(M8Name != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetM8(), cell_len, stream);
x_offset += char_offset;
}
if(Comments != 0) {
psdrv.MoveTo(stream, x_offset, psdrv.row);
psdrv.PrintLine(strdb.GetCM(), cell_len, stream);
x_offset += char_offset;
}
psdrv.row -= psdrv.FontSize();
lines++;
if(orientation == 0)
line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
else
line_points = x_offset - PRINTABLE_OFFSET_X;
psdrv.drawLine(stream, line_points, psdrv.StartX(), psdrv.row);
psdrv.row -= LINE_WIDTH + psdrv.FontSize();
lines++; // Increment the line count
if(lines >= psdrv.LinesPerPage()) {
psdrv.EndPage(stream);
psdrv.StartPage(psdrv.page_count + 1, stream);
if(orientation == 0)
x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
else
x_offset = PRINTABLE_OFFSET_X;
psdrv.row = psdrv.StartY();
lines = 4;
psdrv.MoveTo(stream, psdrv.StartX(), psdrv.row);
psdrv.ChangeFont(stream, item_font, font_size);
x_offset = PrintPSItemBar(stream, psdrv, x_offset,
char_offset, cell_len);
psdrv.ChangeFont(stream, cell_font, font_size);
if(orientation == 0)
line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
else
line_points = x_offset - PRINTABLE_OFFSET_X;
psdrv.row -= (int)psdrv.FontSize();
lines++;
psdrv.drawThickLine(stream, line_points, psdrv.StartX(), psdrv.row);
psdrv.row -= THICK_LINE_WIDTH + psdrv.FontSize();
lines ++;
}
dllistptr = dllistptr->GetNext();
}
psdrv.EndPage(stream);
psdrv.Epilogue(stream, psdrv.page_count);
dllist->Clear();
terminal->Write("Finished", p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
stream.close();
}
void HTMLPrint()
{
Coords *p = new Coords(0, 0);
terminal->ClearScreen();
if(DB->RebuildIndex()) {
terminal->Write("The index file needs to be rebuilt.",
p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
return;
}
char buf[CBuf];
int i;
for(i = 0; i < CBuf; i++) buf[i] = 0;
terminal->Write("Enter file name to print to: ",
p->XPos(), p->YPos());
terminal->GetString(buf);
if(VBDFile::Exists(buf)) {
terminal->Write("File: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->Write(" already exists.");
int yn = terminal->YesNo("Overwrite it (y/n)?", p->XPos(), p->YOffset(2));
if(!yn) {
delete p;
return;
}
}
ofstream stream(buf, ios::out); // Open file and truncate it
terminal->Write("Printing to: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
if(!stream) { // Could not open the stream
terminal->Write("Could not write to: ",
p->XPos(), p->YOffset(2));
terminal->Write(buf);
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
return;
}
terminal->Write("Printing...", p->XPos(), p->YOffset(2));
LoadIndexKeys();
HyperText htm(stream);
char date[255]; htm.GetSystemTime(date);
htm << comment << "HTML file generated by: " << ProgramName << " version ";
htm.precision(3);
htm << VersionNumber << ecomment << endl;
htm << comment << "File Creation date: " << date << ecomment << endl;
htm.Prologue(ProgramName);
htm.StartBody("BGCOLOR=\"#FFFFFF\"");
htm.eat_space(); // Use non-breaking spaces
htm.GenTable();
int num_columns = 0;
// Calculate the number of columns
if(KeyName != 0) num_columns++;
if(M2Name != 0) num_columns++;
if(M3Name != 0) num_columns++;
if(M4Name != 0) num_columns++;
if(M5Name != 0) num_columns++;
if(M6Name != 0) num_columns++;
if(M7Name != 0) num_columns++;
if(M8Name != 0) num_columns++;
if(Comments != 0) num_columns++;
// Write the table title
htm.StartTableRow();
htm.TableHeader("CENTER", num_columns, 1, 10);
char sys_time[255];
htm.GetSystemTime(sys_time);
htm << ' ' << ProgramName << ' ' << br << ' ' << sys_time << ' ';
htm.EndTableHeader();
htm.EndTableRow();
// Write the table headers
htm.StartTableRow();
if(KeyName != 0) {
htm.TableHeader();
htm << ' ' << KeyName << ' ';
htm.EndTableHeader();
}
if(M2Name != 0) {
htm.TableHeader();
htm << ' ' << M2Name << ' ';
htm.EndTableHeader();
}
if(M3Name != 0) {
htm.TableHeader();
htm << ' ' << M3Name << ' ';
htm.EndTableHeader();
}
if(M4Name != 0) {
htm.TableHeader();
htm << ' ' << M4Name << ' ';
htm.EndTableHeader();
}
if(M5Name != 0) {
htm.TableHeader();
htm << ' ' << M5Name << ' ';
htm.EndTableHeader();
}
if(M6Name != 0) {
htm.TableHeader();
htm << ' ' << M6Name << ' ';
htm.EndTableHeader();
}
if(M7Name != 0) {
htm.TableHeader();
htm << ' ' << M7Name << ' ';
htm.EndTableHeader();
}
if(M8Name != 0) {
htm.TableHeader();
htm << ' ' << M8Name << ' ';
htm.EndTableHeader();
}
if(Comments != 0) {
htm.TableHeader();
htm << ' ' << Comments << ' ';
htm.EndTableHeader();
}
htm.EndTableRow();
StrDB strdb(DB);
dllistptr = dllist->GetFront();
while(!dllist->IsHeader(dllistptr)) {
strdb.ReadObject(dllistptr->Data.object_address);
htm.StartTableRow();
if(KeyName != 0) {
htm.TableData();
htm << strdb.GetKM();
htm.EndTableData();
}
if(M2Name != 0) {
htm.TableData();
htm << strdb.GetM2() << ' ';
htm.EndTableData();
}
if(M3Name != 0) {
htm.TableData();
htm << strdb.GetM3() << ' ';
htm.EndTableData();
}
if(M4Name != 0) {
htm.TableData();
htm << strdb.GetM4() << ' ';
htm.EndTableData();
}
if(M5Name != 0) {
htm.TableData();
htm << strdb.GetM5() << ' ';
htm.EndTableData();
}
if(M6Name != 0) {
htm.TableData();
htm << strdb.GetM6() << ' ';
htm.EndTableData();
}
if(M7Name != 0) {
htm.TableData();
htm << strdb.GetM7() << ' ';
htm.EndTableData();
}
if(M8Name != 0) {
htm.TableData();
htm << strdb.GetM8() << ' ';
htm.EndTableData();
}
if(Comments != 0) {
htm.TableData();
htm << strdb.GetCM() << ' ';
htm.EndTableData();
}
htm.EndTableRow();
dllistptr = dllistptr->GetNext();
}
htm.EndTable();
htm.Epilogue();
dllist->Clear();
terminal->Write("Finished", p->XPos(), p->YOffset(2));
terminal->AnyKey(p->XPos(), p->YOffset(2));
delete p; // Free the Coords pointer
stream.close();
}
// Main prorgram thread
int main(int argc, char **argv)
{
// Display the program version information and exit the program
if(argc >= 2) {
if(strcmp(argv[1], "version") == 0) Version();
}
char *FileName;
char *CurrentCfgFile;
char *CfgFile;
Config *CfgData = new Config;
char *AdminUser = 0;
// Look for CfgFile name in environment
if((CurrentCfgFile = getenv(EnvSetting)) == 0)
CfgFile = (char *)DefaultCfgFile;
else
CfgFile = CurrentCfgFile;
// Use default file name if no file is specifed on command line
if(argc < 2) {
int FileStatus = CfgData->Load((char *)CfgFile);
if(!FileStatus) {
printf("\nCannot locate any database files!\n");
exit(0);
}
else {
FileName = CfgData->GetStrValue("DBFileName");
// *********************************************************** //
// Add config file entries needed to initialize the program
// *********************************************************** //
FileName = CfgData->GetStrValue("DBFileName");
AdminUser = CfgData->GetStrValue("AdminUser");
// *********************************************************** //
if(!FileName) {
printf("\nDBFileName section missing in config file: %s\n", CfgFile);
exit(0);
}
}
}
else {
FileName = argv[1];
}
if(!AdminUser) {
AdminRights = 0;
}
else {
int result = strcmp(AdminUser, "TRUE");
if(result == 0) {
AdminRights = 1;
}
else {
AdminRights = 0;
}
}
CfgData->UnLoad(); // Unload the Config file from memory
// Initialize global database pointer
// NOTE: Index file and data file will share the same file name
// with different file extensions. The data file will have a
// .pod extension and the index file will have a .btx extension.
if(AdminRights == 1)
DB = new POD(FileName, RWMode, 1, CacheSize);
else
DB = new POD(FileName, ROMode, 1, CacheSize);
terminal->init();
MainMenu();
terminal->finish();
delete DB;
return 0;
}
// ----------------------------------------------------------- //
// ------------------------------- //
// --------- End of File --------- //
// ------------------------------- //